# -*- coding: utf-8 -*-

"""
  @author: tangliqi
  @date: 2022/11/18 10:46
  @python version: 3.6 
  @contact me: 110
  ---------------------------------------
  @desc: python设计模式实现 => 适配器模式.py
"""
from abc import abstractmethod


# 适配器主要用于适配不同的接口
# 适配器有两种实现方式：1.类适配器(基于继承实现) 2.对象适配器(基于组合实现)
# 适配器常用于： 1.封装有缺陷的接口 2.统一异构的不同类 3.兼容老版本的接口 4.替换依赖的外部类 5.适配不同格式的数据
# 适配器的构成: 1.抽象类，定义要转化成的接口需要实现的方法 2.待适配类：需要被适配的原始类 3.适配器类：

# 用一个展示不同系统的系统版本和基础性能信息的例子展示
# 不同系统暴露出的展示系统信息和性能的接口都不一样。
# 需要用一个类统一接入到自己的系统中，并且在自己的系统中通过统一的方式调用显示不同的系统的信息。

# ============================  抽象类  ============================
class Adapter:
    @abstractmethod
    def watch(self):
        """
        数据返回格式：{"cpu": "", "mem": ""}
        """
        pass

    @abstractmethod
    def info(self):
        """
        数据返回格式：{"version":""}
        """
        pass


# ============================  待适配类  ============================
class System1:
    def system_info(self):
        system = "linux7"
        return system

    def system_monitor(self):
        cpu_use = "40%"
        mem_use = "70%"
        return cpu_use, mem_use


class System2:
    def sys_info(self):
        system_version = "windows10"
        return system_version

    def monitor_info(self):
        cpu_use = "30%"
        mem_use = "80%"
        return cpu_use, mem_use


# ============================  不同的适配器类  ============================
# 当有一个需要适配的系统时，就需要一个对应的适配器类，这样会导致适配器类特别多，难以维护和访问。
# 可以通过工厂方法，将所有的适配器合在一起，通过统一的工厂类进行创建和调用。

# ========= 基于继承实现start =========

class System1Adapter(Adapter, System1):
    def watch(self):
        cpu_use, mem_use = self.system_monitor()
        watch_dict = {"cpu": cpu_use, "mem": mem_use}
        return watch_dict

    def info(self):
        version = self.system_info()
        info_dict = {"version": version}
        return info_dict


class System2Adapter(Adapter, System2):
    def watch(self):
        cpu_use, mem_use = self.monitor_info()
        watch_dict = {"cpu": cpu_use, "mem": mem_use}
        return watch_dict

    def info(self):
        version = self.sys_info()
        info_dict = {"version": version}
        return info_dict


# ========= 基于继承实现end =========

# ========= 基于组合实现start =========
# 基于组合实现的方法更加灵活
class System1CombineAdapter(Adapter):
    def __init__(self, system: System1):
        self.system = system

    def watch(self, *args, **kwargs):
        return self.system.system_info()

    def info(self, *args, **kwargs):
        return self.system.system_monitor()


class System2CombineAdapter(Adapter):
    def __init__(self, system: System2):
        self.system = system

    def watch(self, *args, **kwargs):
        return self.system.sys_info()

    def info(self, *args, **kwargs):
        return self.system.monitor_info()


# ========= 基于组合实现end =========


# ============================  适配器的访问工厂类  ============================
class AdapterFactory(Adapter):
    SYSTEM_TYPE_MAP = {
        "system1": System1Adapter,
        "system2": System2Adapter
    }

    def __init__(self, system_type):
        self.system_adapter = self.SYSTEM_TYPE_MAP[system_type]

    def watch(self):
        return self.system_adapter().watch()

    def info(self):
        return self.system_adapter().info()


if __name__ == '__main__':
    # ==== 通过适配器工厂类及构造参数生成不同的适配器调用 ====
    fac1 = AdapterFactory("system1")
    print(fac1.watch())
    print(fac1.info())

    fac2 = AdapterFactory("system2")
    print(fac2.watch())
    print(fac2.info())

    # ====== 基于组合实现的适配器类 ======
    system1 = System1CombineAdapter(System1())
    print(system1.watch())
    print(system1.info())

    system2 = System2CombineAdapter(System2())
    print(system2.watch())
    print(system2.info())
